package com.example.demo.controller;

import com.example.demo.common.*;
import com.example.demo.model.ArticleInfo;
import com.example.demo.model.UserInfo;
import com.example.demo.model.UserInfoVO;
import com.example.demo.service.ArticleService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: lishuo
 * Date: 2023-09-16
 * Time: 15:54
 */
@RestController
@RequestMapping("/art")
public class ArticleController {
    @Autowired
    private ArticleService articleService;

    @Autowired
    private UserService userService;

    // 得到当前登录用户的文章列表
    @RequestMapping("/mylist")
    public ResultAjax getMylist(HttpServletRequest request) throws ExecutionException, InterruptedException {
        // 1.得到当前用户登录信息
        UserInfo user = SessionUtils.getUser(request);
        if (user == null) {
            return ResultAjax.fail("用户未登录!");
        }

        // 2.根据 id 查询作者信息
        FutureTask<UserInfoVO> userTask = new FutureTask<>(new Callable<UserInfoVO>() {
            @Override
            public UserInfoVO call() throws Exception {
                return userService.getUserById(user.getId());
            }
        });
        // 3.根据作者 id 查询发布文章数量
        FutureTask<Integer> artCountTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return articleService.getArtCount(user.getId());
            }
        });
        // 2、3 可以使用线程池并发查询
        ThreadPoolExecutor threadPool = MyThreadPool.getThreadPool();
        threadPool.submit(userTask);
        threadPool.submit(artCountTask);

        // 4.数据整合（作者信息+文章数量）
        UserInfoVO userInfoVO = userTask.get();
        int artCount = artCountTask.get();
        // 拿到结果后进行组装
        userInfoVO.setArtCount(artCount);


        // 5.根据用户 id 查询此用户发表的所有文章
        List<ArticleInfo> articles = articleService.getListByUid(user.getId());

        // 6.并行处理摘要部分
        if (articles != null && articles.size() > 0) {
            // 并行处理 articles 集合
            articles.stream().parallel().forEach((art) -> {
                String content = Convert.convert(art.getContent());
                if (art.getContent().length() > 150) {
                    content = content.substring(0,150)+". . .";
                }
                art.setContent(content);
            });
        }
        // 7.将结果返回给前端
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("arts",articles);
        hashMap.put("user",userInfoVO);
        return ResultAjax.succ(hashMap);
    }

    // 文章删除功能
    @RequestMapping("/del")
    public ResultAjax del(Integer id,HttpServletRequest request) {
        // 1.参数校验
        if (id == null || id <= 0) {
            return ResultAjax.fail("非法传参!");
        }
        // 2.得到当前用户
        UserInfo userInfo = SessionUtils.getUser(request);
        if (userInfo == null) {
            return ResultAjax.fail("用户未登录!");
        }
        // 3.验证文章归属人并删除文章
        int result = articleService.del(id,userInfo.getId());
        // 4.将结果返回给前端
        return ResultAjax.succ(result);
    }

    // 文章添加功能
    @RequestMapping("/add")
    public ResultAjax add(ArticleInfo articleInfo,HttpServletRequest request) {
        // 1.参数效验
        if (articleInfo == null || !StringUtils.hasLength(articleInfo.getTitle().trim())
        || !StringUtils.hasLength(articleInfo.getContent().trim())) {
            return ResultAjax.fail("非法传参!");
        }

        // 2.组装数据（文章信息+文章归属）
        UserInfo userInfo = SessionUtils.getUser(request);
        if (userInfo == null) {
            return ResultAjax.fail("用户未登录!");
        }
        articleInfo.setUid(userInfo.getId());
        // 3.将数据添加到数据库
        int result = articleService.add(articleInfo);

        // 4.将结果返回给前端
        return ResultAjax.succ(result);
    }

    // 文章修改功能(获取文章原始内容+修改文章内容)
    @RequestMapping("/getart")
    public ResultAjax getart(Integer aid,HttpServletRequest request) {
        // 1.参数校验
        if (aid == null || aid <= 0) {
            return ResultAjax.fail("非法传参!");
        }
        // 2.验证用户身份(归属人判断)
        UserInfo userInfo = SessionUtils.getUser(request);
        if (userInfo == null) {
            return ResultAjax.fail("用户未登录!");
        }
        // 3.查询文章并判断用户权限
        ArticleInfo articleInfo = articleService.getArticleByidAnduid(aid, userInfo.getId());
        // 4.将结果返回给前端
        return ResultAjax.succ(articleInfo);
    }


    @RequestMapping("/update")
    public ResultAjax update(ArticleInfo articleInfo,HttpServletRequest request) {
        // 1.参数校验
        if (articleInfo == null || !StringUtils.hasLength(articleInfo.getTitle().trim())
                || !StringUtils.hasLength(articleInfo.getContent().trim())) {
            return ResultAjax.fail("非法传参!");
        }

        // 2.组装数据（文章信息+文章归属）
        UserInfo userInfo = SessionUtils.getUser(request);
        if (userInfo == null) {
            return ResultAjax.fail("用户未登录!");
        }
        articleInfo.setUid(userInfo.getId());
        articleInfo.setUpdatetime(LocalDateTime.now());
        // 3.修改数据库并校验权限
        int result = articleService.update(articleInfo);
        // 4.将结果返回给前端
        return ResultAjax.succ(result);
    }

    // 文章详情页（用户信息+文章信息）
    @RequestMapping("/detail")
    public ResultAjax getDetail(Integer aid) throws ExecutionException, InterruptedException {
        // 1.校验参数
        if (aid == null || aid <= 0) {
            return ResultAjax.fail("非法传参!");
        }
        // 2.根据 aid 查询文章信息
        ArticleInfo article = articleService.getArticleById(aid);
        if (article == null) {
            return ResultAjax.fail("非法传参!");
        }
        // 3.根据 uid 查询作者信息
        FutureTask<UserInfoVO> userTask = new FutureTask<>(new Callable<UserInfoVO>() {
            @Override
            public UserInfoVO call() throws Exception {
                return userService.getUserById(article.getUid());
            }
        });
        // 4.根据作者 uid 查询发布文章数量
        FutureTask<Integer> artCountTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                return articleService.getArtCount(article.getUid());
            }
        });
        // 3、4 可以使用线程池并发查询
        ThreadPoolExecutor threadPool = MyThreadPool.getThreadPool();
        threadPool.submit(userTask);
        threadPool.submit(artCountTask);

        // 5.数据整合（作者信息+文章数量）
        UserInfoVO userInfoVO = userTask.get();
        int artCount = artCountTask.get();
        // 拿到结果后进行组装
        userInfoVO.setArtCount(artCount);

        // 6.将结果返回给前端
        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("art",article);
        hashMap.put("user",userInfoVO);
        return ResultAjax.succ(hashMap);
    }

    // 动态访问量
    @RequestMapping("/incre_rcount")
    public ResultAjax increaseRcount(Integer aid) {
        // 1.校验参数
        if (aid == null || aid <= 0) {
            return ResultAjax.fail("非法传参");
        }
        // 2.修改数据库中的 rcount
        int result = articleService.increRcount(aid);
        // 3.将结果返回给前端
        return ResultAjax.succ(result);
    }

    // 带有分页功能的文章列表页
    @RequestMapping("/getlistbypage")
    public ResultAjax getListByPage(Integer pIndex,Integer pSize) throws ExecutionException, InterruptedException {
        // 1.参数矫正
        if (pIndex == null || pIndex < 1) {
            pIndex = 1;
        }
        if (pSize == null || pSize < 3) {
            pSize = 3;
        }

        // 2.并发查询文章列表页和总页数
        // 2.1 查询文章列表
        int finalLimit = pSize;
        int finalOffset = pSize*(pIndex - 1);
        FutureTask<List<ArticleInfo>> artsTask = new FutureTask<>(new Callable<List<ArticleInfo>>() {
            @Override
            public List<ArticleInfo> call() throws Exception {
                return articleService.getListByPage(finalLimit,finalOffset);
            }
        });
        // 2.2 查询总页数
        FutureTask<Integer> pCountTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int pageCount = 1;
                // 得到文章总数
                int totalArticle = articleService.getCount();
                // 向上取整
                if (totalArticle > finalLimit) {
                     if ( totalArticle % finalLimit != 0 ) {
                        pageCount = totalArticle / finalLimit + 1;
                     } else {
                         pageCount = totalArticle / finalLimit;
                     }
                }
                 return pageCount;
            }
        });
        // 并发执行
        MyThreadPool.getThreadPool().submit(artsTask);
        MyThreadPool.getThreadPool().submit(pCountTask);


        // 3.组装数据
        List<ArticleInfo> articles = artsTask.get();
        int pageCount = pCountTask.get();

        // 并行处理摘要部分
        if (articles != null && articles.size() > 0) {
            // 并行处理 articles 集合
            articles.stream().parallel().forEach((art) -> {
                String content = Convert.convert(art.getContent());
                if (art.getContent().length() > 150) {
                    content = content.substring(0,150)+". . .";
                }
                art.setContent(content);
            });
        }

        HashMap<String,Object> hashMap = new HashMap<>();
        hashMap.put("articles",articles);
        hashMap.put("pageCount",pageCount);

        // 4.将结果返回给前端
        return ResultAjax.succ(hashMap);
    }
}
